package com.mc.lp.database.service.handler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.util.CollectionUtils;

import com.mc.lp.database.exception.DataNotFoundException;
import com.mc.lp.database.service.handler.constant.FormRequestType;
import com.mc.lp.service.RecommendationService;
import com.mc.lp.shared.util.constants.ResponseStatus;
import com.mc.lp.shared.vo.IValueObject;
import com.mc.lp.shared.vo.RecommendationVO;
import com.mc.lp.shared.vo.SearchCriteriaVO;
import com.mc.lp.shared.vo.ServiceResponse;
import com.mc.lp.shared.vo.SimpleResponse;
import com.mc.lp.shared.vo.StudentRecordVO;

/*
 * @author aphanda
 * @date Dec 27, 2014
 * @time 2:54:55 PM
 */

// DV Deepak Please remove ur tags if you have worked that particular task and
// Also lets make a practice to add Business criticality with the tags like Business Priority 1-5 (1 being most critical)
// with Tag line e.g. AP BP-1 Add recommendation code. 

public class RecommendationHandler extends AbstractFormHandler<IValueObject, IValueObject> {

	@Resource
	RecommendationService recommendationService;

	@Override
	public HashSet<FormRequestType> getRequestHandlingType() {
		HashSet<FormRequestType> handledRequest = new HashSet<FormRequestType>();
		handledRequest.add(FormRequestType.RECOMMENDATION_SAVE);
		handledRequest.add(FormRequestType.RECOMMENDATION_UPDATE);
		handledRequest.add(FormRequestType.RECOMMENDATION_DELETE);
		handledRequest.add(FormRequestType.RECOMMENDATION_GET);
		return handledRequest;
	}

	@Override
	public IValueObject serveRequest(FormRequestType requestType, IValueObject object) throws Exception {
		SimpleResponse response = new SimpleResponse();
		response.setMsg("No case matched to perform operation, please check request type");

		switch (requestType) {
		case RECOMMENDATION_SAVE:
			ServiceResponse<RecommendationVO> result = saveRecommendations(requestType, object);
			if (!ResponseStatus.SUCCESS.equals(result.getStatus())) {
				response.setMsg("Input Not Valid, please check posted values");
				return response;
			}
			return result;
		case RECOMMENDATION_GET:
			ServiceResponse<RecommendationVO> getResult = getRecommendations(requestType, object);
			if (!ResponseStatus.SUCCESS.equals(getResult.getStatus())) {
				response.setMsg("Input Not Valid, please check posted values");
				return response;
			} else {
				return getResult;
			}
		case RECOMMENDATION_DELETE:
			return deleteRecommendation(requestType, object);
		default:
			return response;
		}
	}

	private ServiceResponse<RecommendationVO> deleteRecommendation(FormRequestType requestType, IValueObject object) {
		List<RecommendationVO> deleteRecommendations = new ArrayList<RecommendationVO>();
		ServiceResponse<RecommendationVO> serviceResponse = new ServiceResponse<RecommendationVO>();
		if (object != null && object instanceof StudentRecordVO) {
			StudentRecordVO studentRecord = ((StudentRecordVO) object);
			List<RecommendationVO> recommendations = studentRecord.getRecommendations();
			if (!CollectionUtils.isEmpty(recommendations)) {
				for (RecommendationVO recommendation : recommendations) {
					try {
						boolean result = recommendationService.deleteRecommendation(recommendation.getId());
						if (result) {
							deleteRecommendations.add(recommendation);
							serviceResponse.setStatus(ResponseStatus.SUCCESS);
						}
					} catch (DataNotFoundException e) {
						serviceResponse.setMsg(serviceResponse.getMsg() + ", " + e.getMessage());
						serviceResponse.setStatus(ResponseStatus.FAILED);
					}
				}
				serviceResponse.setResult(deleteRecommendations);
			}
		}
		return serviceResponse;
	}

	private ServiceResponse<RecommendationVO> saveRecommendations(FormRequestType requestType, IValueObject object) throws DataNotFoundException {
		// AP save recommendations based on record type
		ServiceResponse<RecommendationVO> serviceResponse = new ServiceResponse<RecommendationVO>();
		List<RecommendationVO> recommendations = new ArrayList<RecommendationVO>();
		if (object instanceof StudentRecordVO) {
			StudentRecordVO studentRecord = (StudentRecordVO) object;
			if (!CollectionUtils.isEmpty(studentRecord.getRecommendations())) {
				for (RecommendationVO recommendationVo : studentRecord.getRecommendations()) {
					recommendationVo.setSearchCriteria(studentRecord.getSearchCriteria());
					recommendationService.saveRecommendations(recommendationVo);
					recommendations.add(recommendationVo);
				}
			}
			serviceResponse.setResult(recommendations);
			serviceResponse.setStatus(ResponseStatus.SUCCESS);
			return serviceResponse;
		} else {
			return null;
		}
	}

	private ServiceResponse<RecommendationVO> getRecommendations(FormRequestType requestType, IValueObject object) throws DataNotFoundException {
		ServiceResponse<RecommendationVO> serviceResponse = new ServiceResponse<RecommendationVO>();
		SearchCriteriaVO crit = new SearchCriteriaVO();
		crit = ((StudentRecordVO) object).getSearchCriteria();
		try {
			List<RecommendationVO> recommendations = recommendationService.getRecommendationBySearchCriteria(crit);
			serviceResponse.setResult(recommendations);
			serviceResponse.setStatus(ResponseStatus.SUCCESS);
		} catch (DataNotFoundException e) {
			serviceResponse.setStatus(ResponseStatus.NOT_FOUND);
		} catch (Exception e) {
			// log exception here
			serviceResponse.setStatus(ResponseStatus.FAILED);
		}
		return serviceResponse;
	}
}
